package com.fjwt.gz.core.third.util.jilin;

import org.apache.commons.codec.binary.Base64;

import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

/**
 * RSAf分段加密、解密
 *
 * @author ruoyi
 **/
public class RsaFgmUtils
{
    // Rsa 私钥
    public static String privateKey = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAJePu2GPe7tKu+PDGBEI0ml6I+IlPb56e5bY851i8WQ6X9nBxLeddHSloTosXxliRbJ1RQKT3T+bdNRb8+Sd7RdyhOEYMX+PVvc9bSco3gggYEJz6C9Rfqd4OWdGALJ4QlGGXRsfKUp9EF7zZJW1E0qQZP5QB4OpEXHyCIhNXFYNAgMBAAECgYEAlwnvA++4r9JvYjCHaFpxThohbnoMiSmIxrCYPq1ewLKH2PuIbi+k4aY6AT4825Aawxio2EPBBmWGzSaB7MARiHJg/gU6dOEJNqVpeOpph9FcXm5XSrTlNbwFcSPvuOojeNYsUx9L+awZo1cZgjPLmffp/9b2SuUXUnV2RGXZFCUCQQDkwInvlom9/VjB2wvyxQVQXqYGwnYeLGpTPhxuSnauxh/d+DSb10R2Kff1KYvVK8ixJa2K4sYn35FNejdb4zYvAkEAqZ1gg5t3J4hFzgFwvGGWXs3uNlHP5xZR2fMritLLCYcYQ24AN0oaGHaHOdKQwCTJ+BkwgdNxMb3UGL61ndckgwJACxJWmsYKfKuadCeJ+IIYs78hAgq/dM5phwXmkmAARo1IVZIB2dkdcyqs2azdG8A2wnw0XhiDxsJHYhycOVJR+QJBAJCyXpTHuwXxnkNZPTioM+Ta3z5d2vP0OY2qglni7C1Ln6penDaOs+Zsr33noW8Zs2dA7f3DSQy7OcaGY1+tG0sCQD3HiYJjQYVeb8+ZBFkg06QluUdoUjRnwtIAN2yN44PCVe0hSpVvdugG0Hvsh/a527YcB4thO67bmlY19R9L39c=";
    // Rsa 公钥
    public static String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCXj7thj3u7SrvjwxgRCNJpeiPiJT2+enuW2POdYvFkOl/ZwcS3nXR0paE6LF8ZYkWydUUCk90/m3TUW/Pkne0XcoThGDF/j1b3PW0nKN4IIGBCc+gvUX6neDlnRgCyeEJRhl0bHylKfRBe82SVtRNKkGT+UAeDqRFx8giITVxWDQIDAQAB";
    // 秘钥
    private static final int ENCRYPT_LENGTH = 1024;

    /**
     * 私钥解密
     *
     * @param text 待解密的文本
     * @return 解密后的文本
     */
    public static String decryptByPrivateKey(String text) throws Exception
    {
        return decryptByPrivateKey(privateKey, text);
    }

    /**
     * 公钥解密
     *
     * @param publicKeyString 公钥
     * @param text 待解密的信息
     * @return 解密后的文本
     */
    public static String decryptByPublicKey(String publicKeyString, String text) throws Exception
    {
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyString));
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, publicKey);

        // 分段解密
        int keySize = ENCRYPT_LENGTH;
        // 最大块大小
        int maxBlockSize = keySize / 8;
        byte[] encryptedData = Base64.decodeBase64(text);
        ByteArrayOutputStream out = new ByteArrayOutputStream();

        for (int i = 0; i < encryptedData.length; i += maxBlockSize) {
            int inputLen = encryptedData.length - i;
            if (inputLen > maxBlockSize) {
                inputLen = maxBlockSize;
            }
            byte[] block = cipher.doFinal(encryptedData, i, inputLen);
            out.write(block);
        }

        // 返回解密后的字符串
        byte[] decryptedData = out.toByteArray();
        out.close();
        return new String(decryptedData);
    }

    /**
     * 私钥加密
     *
     * @param privateKeyString 私钥
     * @param text 待加密的信息
     * @return 加密后的文本
     */
    public static String encryptByPrivateKey(String privateKeyString, String text) throws Exception
    {
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyString));
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, privateKey);

        // 分段加密
        int keySize = ENCRYPT_LENGTH;
        // 最大块大小
        int maxBlockSize = keySize / 8 - 11;
        byte[] data = text.getBytes();
        ByteArrayOutputStream out = new ByteArrayOutputStream();

        for (int i = 0; i < data.length; i += maxBlockSize) {
            int inputLen = data.length - i;
            if (inputLen > maxBlockSize) {
                inputLen = maxBlockSize;
            }
            byte[] block = cipher.doFinal(data, i, inputLen);
            out.write(block);
        }

        // 返回 Base64 编码的加密结果
        byte[] encryptedData = out.toByteArray();
        out.close();
        return Base64.encodeBase64String(encryptedData);
    }

    /**
     * 私钥解密
     *
     * @param privateKeyString 私钥
     * @param text 待解密的文本
     * @return 解密后的文本
     */
    public static String decryptByPrivateKey(String privateKeyString, String text) throws Exception
    {
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec5 = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyString));
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec5);
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        // 分段解密
        int keySize = ENCRYPT_LENGTH;
        // 最大块大小
        int maxBlockSize = keySize / 8;
        byte[] encryptedData = Base64.decodeBase64(text);
        ByteArrayOutputStream out = new ByteArrayOutputStream();

        for (int i = 0; i < encryptedData.length; i += maxBlockSize) {
            int inputLen = encryptedData.length - i;
            if (inputLen > maxBlockSize) {
                inputLen = maxBlockSize;
            }
            byte[] block = cipher.doFinal(encryptedData, i, inputLen);
            out.write(block);
        }

        // 返回解密后的字符串
        byte[] decryptedData = out.toByteArray();
        out.close();
        return new String(decryptedData);
    }

    /**
     * 公钥加密
     *
     * @param publicKeyString 公钥
     * @param text 待加密的文本
     * @return 加密后的文本
     */
    public static String encryptByPublicKey(String publicKeyString, String text) throws Exception
    {
        // 解码公钥
        X509EncodedKeySpec x509EncodedKeySpec2 = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyString));
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec2);

        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);

        // 分段加密
        int keySize = ENCRYPT_LENGTH;
        // 最大块大小
        int maxBlockSize = keySize / 8 - 11;
        byte[] data = text.getBytes();
        ByteArrayOutputStream out = new ByteArrayOutputStream();

        for (int i = 0; i < data.length; i += maxBlockSize) {
            int inputLen = data.length - i;
            if (inputLen > maxBlockSize) {
                inputLen = maxBlockSize;
            }
            byte[] block = cipher.doFinal(data, i, inputLen);
            out.write(block);
        }

        // 返回 Base64 编码的加密结果
        byte[] encryptedData = out.toByteArray();
        out.close();
        return Base64.encodeBase64String(encryptedData);
    }

    /**
     * 构建RSA密钥对
     *
     * @return 生成后的公私钥信息
     */
    public static RsaKeyPair generateKeyPair() throws NoSuchAlgorithmException
    {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        keyPairGenerator.initialize(ENCRYPT_LENGTH);
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
        RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
        String publicKeyString = Base64.encodeBase64String(rsaPublicKey.getEncoded());
        String privateKeyString = Base64.encodeBase64String(rsaPrivateKey.getEncoded());
        return new RsaKeyPair(publicKeyString, privateKeyString);
    }

    /**
     * RSA密钥对对象
     */
    public static class RsaKeyPair
    {
        private final String publicKey;
        private final String privateKey;

        public RsaKeyPair(String publicKey, String privateKey)
        {
            this.publicKey = publicKey;
            this.privateKey = privateKey;
        }

        public String getPublicKey()
        {
            return publicKey;
        }

        public String getPrivateKey()
        {
            return privateKey;
        }
    }


}